package utils

import (
	"core/graylog"
	"fmt"
	"runtime"
	"runtime/debug"
)

// CatchPanic 捕捉panic
func CatchPanic() {
	if err := recover(); err != nil {
		var stack string
		for i := 1; ; i++ {
			_, file, line, ok := runtime.Caller(i)
			if !ok {
				break
			}
			stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
		}
		Error("catch panic, err:", err)
		Error("catch panic, path:", stack)
	}
}

// CatchPanicAndErr 捕捉panic和err，并记log
func CatchPanicAndErr(fileMark string, e *error, data graylog.M) {
	if data == nil {
		data = make(graylog.M)
	}
	if panicErr := recover(); panicErr != nil {
		data["errInfo"] = fmt.Sprintf("[run time panic]: %v", panicErr)
		data["fileMark"] = fileMark
		data["stack"] = string(debug.Stack())
		graylog.Info("程序异常", data)
	}
	if e != nil && *e != nil {
		err := *e
		data["errInfo"] = err.Error()
		data["fileMark"] = fileMark
		data["stack"] = string(debug.Stack())
		graylog.Info("程序异常", data)
	}
}

// 捕捉err，并记log
func CatchErr(fileMark string, e *error, data graylog.M) {
	if data == nil {
		data = make(graylog.M)
	}
	if panicErr := recover(); panicErr != nil {
		data["errInfo"] = fmt.Sprintf("[run time panic]: %v", panicErr)
		data["fileMark"] = fileMark
		data["stack"] = string(debug.Stack())
		graylog.Info("程序异常", data)
	}
	if e != nil && *e != nil {
		err := *e
		data["errInfo"] = err.Error()
		data["fileMark"] = fileMark
		data["stack"] = string(debug.Stack())
		graylog.Info("程序异常", data)
	}
}

func SageGoAndCatchErr(f func() error) {
	err := f()
	if err != nil {
		graylog.Info("程序异常", graylog.M{
			"errInfo":  err.Error(),
			"fileMark": "catch-err",
			"stack":    string(debug.Stack()),
		})
	}
}

// 启动安全协程，协程崩溃会被recover
func SafeGo(f func()) {
	defer CatchPanic()
	f()
}
